/* eslint-disable no-console */
import { watch } from 'chokidar'

export class FileWatcher {
  /**
   * 文件监听器（支持动态路径调整与生命周期管理）
   * @param {string|Array} files - 监听路径（支持 glob 模式）
   * @param {object} [options] - 高级配置项
   * @param {Function} [logger] - 自定义日志输出
   */
  constructor(files, options = {}, logger = console.log) {
    // 初始化日志
    this.logger = logger

    // 初始化核心参数
    this._files = files
    this._options = {
      ignored: /(^|[/\\])\../,
      persistent: true,
      ignoreInitial: false,
      ...options,
    }

    // 事件处理器缓存
    this._eventHandlers = new Map()

    // 监听器实例（延迟初始化）
    this._watcher = null
  }

  /**
   * 启动文件监听
   */
  start() {
    if (this._watcher)
      return

    // 创建监听实例
    this._watcher = watch(this._files, this._options)

    // 绑定标准事件
    this._bindEvent('add', path => this.logger(`+ file ${path}`))
    this._bindEvent('unlink', path => this.logger(`- ${path}`))
    this._bindEvent('change', path => this.logger(`~ file ${path}`))
    this._bindEvent('addDir', path => this.logger(`+ dir ${path}`))
    this._bindEvent('unlinkDir', path => this.logger(`- dir ${path}`))
    this._bindEvent('error', error => this.logger(`🐞 监听器错误 - ${error}`))

    // 生命周期钩子
    this._watcher.on('ready', () => {
      this.logger('\u001B[1;32m✅  扫描完成\u001B[0m')
      this.logger('\u001B[1;35m>>> 进入监控状态 <<< \u001B[0m')
    })

    this.logger('\u001B[1;35m>>> 启动文件监控 <<< \u001B[0m')
    this.logger('\u001B[1;36m开始扫描文件...\u001B[0m')
  }

  /**
   * 动态绑定事件处理器
   * @param {string} eventName - 事件类型
   * @param {Function} handler - 回调函数
   */
  _bindEvent(eventName, handler) {
    const wrapper = (...args) => handler(...args)
    this._watcher.on(eventName, wrapper)
    this._eventHandlers.set(eventName, wrapper)
  }

  /**
   * 停止监听并释放资源
   */
  stop() {
    if (!this._watcher)
      return

    // 移除所有事件监听
    this._eventHandlers.forEach((handler, eventName) => {
      this._watcher.removeListener(eventName, handler)
    })

    this._watcher.close()
    this._watcher = null
    this._eventHandlers.clear()

    this.logger('\u001B[131m🛑 已终止文件监控\u001B[0m')
  }

  /**
   * 重新启动监听器
   */
  restart() {
    this.stop()
    this.start()
  }

  /**
   * 动态添加监听路径（扩展功能）
   * @param {string|Array} newPaths - 新增路径
   */
  addPaths(newPaths) {
    if (!this._watcher)
      return
    this._watcher.add(Array.isArray(newPaths) ? newPaths : [newPaths])
  }

  /**
   * 动态移除监听路径（扩展功能）
   * @param {string|Array} removePaths - 移除路径
   */
  removePaths(removePaths) {
    if (!this._watcher)
      return
    this._watcher.unwatch(Array.isArray(removePaths) ? removePaths : [removePaths])
  }
}
